use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use rusqlite::{Row, Result as SqliteResult};

/// 用户模型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct User {
    pub id: i64,
    pub username: String,
    pub email: Option<String>,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
    pub is_active: bool,
}

impl User {
    pub fn from_row(row: &Row) -> SqliteResult<Self> {
        Ok(User {
            id: row.get("id")?,
            username: row.get("username")?,
            email: row.get("email")?,
            created_at: row.get("created_at")?,
            updated_at: row.get("updated_at")?,
            is_active: row.get("is_active")?,
        })
    }
}

/// 应用配置模型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AppConfig {
    pub id: String,
    pub theme: String,
    pub language: String,
    pub auto_start: bool,
    pub minimize_to_tray: bool,
    pub notifications: bool,
    pub shortcuts: serde_json::Value,
    pub created_at: DateTime<Utc>,
    pub updated_at: DateTime<Utc>,
}

impl AppConfig {
    pub fn from_row(row: &Row) -> SqliteResult<Self> {
        let shortcuts_str: String = row.get("shortcuts")?;
        let shortcuts = serde_json::from_str(&shortcuts_str)
            .unwrap_or(serde_json::json!({}));

        Ok(AppConfig {
            id: row.get("id")?,
            theme: row.get("theme")?,
            language: row.get("language")?,
            auto_start: row.get("auto_start")?,
            minimize_to_tray: row.get("minimize_to_tray")?,
            notifications: row.get("notifications")?,
            shortcuts,
            created_at: row.get("created_at")?,
            updated_at: row.get("updated_at")?,
        })
    }

    pub fn default() -> Self {
        let now = Utc::now();
        Self {
            id: "default".to_string(),
            theme: "system".to_string(),
            language: "en".to_string(),
            auto_start: false,
            minimize_to_tray: true,
            notifications: true,
            shortcuts: serde_json::json!({
                "toggle_window": "CmdOrCtrl+Shift+H",
                "new_item": "CmdOrCtrl+N",
                "search": "CmdOrCtrl+F"
            }),
            created_at: now,
            updated_at: now,
        }
    }
}

/// 日志条目模型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LogEntry {
    pub id: Option<i64>,
    pub level: String,
    pub message: String,
    pub component: Option<String>,
    pub metadata: Option<serde_json::Value>,
    pub created_at: DateTime<Utc>,
}

impl LogEntry {
    pub fn new(level: &str, message: &str) -> Self {
        Self {
            id: None,
            level: level.to_string(),
            message: message.to_string(),
            component: None,
            metadata: None,
            created_at: Utc::now(),
        }
    }

    pub fn with_component(mut self, component: &str) -> Self {
        self.component = Some(component.to_string());
        self
    }

    pub fn with_metadata(mut self, metadata: serde_json::Value) -> Self {
        self.metadata = Some(metadata);
        self
    }

    pub fn from_row(row: &Row) -> SqliteResult<Self> {
        let metadata_str: Option<String> = row.get("metadata")?;
        let metadata = metadata_str
            .and_then(|s| serde_json::from_str(&s).ok());

        Ok(LogEntry {
            id: Some(row.get("id")?),
            level: row.get("level")?,
            message: row.get("message")?,
            component: row.get("component")?,
            metadata,
            created_at: row.get("created_at")?,
        })
    }
}

/// 数据库迁移记录模型
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Migration {
    pub id: i64,
    pub version: i64,
    pub name: String,
    pub applied_at: DateTime<Utc>,
}

impl Migration {
    pub fn from_row(row: &Row) -> SqliteResult<Self> {
        Ok(Migration {
            id: row.get("id")?,
            version: row.get("version")?,
            name: row.get("name")?,
            applied_at: row.get("applied_at")?,
        })
    }
}

/// 通用的数据库模型特征
pub trait Model: Sized {
    /// 从数据库行创建模型实例
    fn from_row(row: &Row) -> SqliteResult<Self>;
    
    /// 获取表名
    fn table_name() -> &'static str;
    
    /// 获取主键字段名
    fn primary_key() -> &'static str {
        "id"
    }
}

impl Model for User {
    fn from_row(row: &Row) -> SqliteResult<Self> {
        User::from_row(row)
    }
    
    fn table_name() -> &'static str {
        "users"
    }
}

impl Model for AppConfig {
    fn from_row(row: &Row) -> SqliteResult<Self> {
        AppConfig::from_row(row)
    }
    
    fn table_name() -> &'static str {
        "app_config"
    }
    
    fn primary_key() -> &'static str {
        "id"
    }
}

impl Model for LogEntry {
    fn from_row(row: &Row) -> SqliteResult<Self> {
        LogEntry::from_row(row)
    }
    
    fn table_name() -> &'static str {
        "logs"
    }
}

impl Model for Migration {
    fn from_row(row: &Row) -> SqliteResult<Self> {
        Migration::from_row(row)
    }
    
    fn table_name() -> &'static str {
        "migrations"
    }
}

/// 查询结果包装器
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueryResult<T> {
    pub data: Vec<T>,
    pub total: usize,
    pub page: Option<usize>,
    pub per_page: Option<usize>,
}

impl<T> QueryResult<T> {
    pub fn new(data: Vec<T>) -> Self {
        let total = data.len();
        Self {
            data,
            total,
            page: None,
            per_page: None,
        }
    }

    pub fn with_pagination(data: Vec<T>, total: usize, page: usize, per_page: usize) -> Self {
        Self {
            data,
            total,
            page: Some(page),
            per_page: Some(per_page),
        }
    }
}

/// 排序方向
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum SortDirection {
    Asc,
    Desc,
}

impl SortDirection {
    pub fn to_sql(&self) -> &'static str {
        match self {
            SortDirection::Asc => "ASC",
            SortDirection::Desc => "DESC",
        }
    }
}

/// 排序选项
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SortOption {
    pub field: String,
    pub direction: SortDirection,
}

impl SortOption {
    pub fn new(field: &str, direction: SortDirection) -> Self {
        Self {
            field: field.to_string(),
            direction,
        }
    }

    pub fn asc(field: &str) -> Self {
        Self::new(field, SortDirection::Asc)
    }

    pub fn desc(field: &str) -> Self {
        Self::new(field, SortDirection::Desc)
    }
}

/// 分页选项
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaginationOption {
    pub page: usize,
    pub per_page: usize,
}

impl PaginationOption {
    pub fn new(page: usize, per_page: usize) -> Self {
        Self { page, per_page }
    }

    pub fn offset(&self) -> usize {
        (self.page - 1) * self.per_page
    }

    pub fn limit(&self) -> usize {
        self.per_page
    }
}

impl Default for PaginationOption {
    fn default() -> Self {
        Self::new(1, 20)
    }
}
